#pragma once
#include <iostream>
#include <memory>

#include <sys/select.h>

#include "Socket.hpp"
#include "Log.hpp"

const static int fd_size = 10;
class Select
{
private:
public:
    Select(uint16_t port)
        : _socket_server(new TCP_Server_Socket(port)), _fd_arr({0})
    {
        _socket_server->ServerInit();
        Add_fd_arr(_socket_server->GetListenfd()); // 将listen_fd放入fd_arr中
    }
    ~Select()
    {
    }
    // select负责等
    void Loop()
    {
        while (true)
        {
            fd_set rfds; // 我只关心读事件
            FD_ZERO(&rfds); // 先清空，以免上一次的rfds干扰
            Add_fd_set(rfds); // 增添本来有的fd

            timeval timeout = {3, 0}; //一次等3秒
            PrintDebug();

            int ret = select(Maxfd() + 1, &rfds, nullptr, nullptr, &timeout); 
            // 等成功了，有就绪的fd
            if (ret > 0)
            {
                Handler(rfds);
            }
            // 在timeout时间到了，没有就绪的fd
            else if (ret == 0)
            {
                std::cout << "没有fd就绪" << std::endl;
            }
            // select error
            else
            {
                _log.LogMessage(ClassFile, Error, "select error, strerror : %s\n", strerror(errno));
                return;
            }
        }
    }

    // select等成功了，执行的方法
    void Handler(fd_set &rfds)
    {
       for(const auto& e : _fd_arr)
       {
            if(e == 0) continue;
            if(FD_ISSET(e, &rfds))
            {
                // accept条件就绪
                if(e == _fd_arr[0])
                {
                    std::cout << "listen 条件就绪" << std::endl; 
                    _socket_server->Accept();
                    Add_fd_arr(_socket_server->Getfd());
                }
                // recv条件就绪
                else
                {
                    std::cout << "recv 条件就绪" << std::endl; 
                    if(!_socket_server->Recv(e)) //读到末尾/读取出错
                    {
                        std::cout << "fd : " << e << "退出" << std::endl;
                        _socket_server->Closefd(e);
                        Delete_fd_arr(e);
                        
                    }   
                }
                FD_CLR(e, &rfds);
            }
       }
    }

private:
    // 寻找最大的fd
    int Maxfd()
    {
        int maxfd = -1;
        for (const auto& e : _fd_arr)
        {
            maxfd = maxfd > e ? maxfd : e;
        }
        return maxfd;
    }
    // 遍历fd_arr，用来将fd们添加到fd_set中
    void Add_fd_set(fd_set &rfds)
    {
        for (auto& e : _fd_arr)
            if(e != 0)
                FD_SET(e, &rfds);
    }
    // 用于将新fd添加到fd_arr 中管理
    void Add_fd_arr(int fd)
    {
        for(auto& e : _fd_arr)
        {
            if(e == 0) 
            {
                e = fd;
                break;
            }
        }        
    }
    // 用于删除没用的fd
    void Delete_fd_arr(int fd)
    {
        for(auto& e : _fd_arr)
            if(e == fd)
                e = 0;
    }


    void PrintDebug()
    {
        std::cout << "当前的fd都有: ";
        for(auto& e : _fd_arr)
            if(e != 0) 
                std::cout << e << " ";
        std::cout << std::endl;
    }

private:
    std::unique_ptr<Socket> _socket_server;
    int _fd_arr[fd_size]; // 用来管理fd
};